﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using Microsoft.VisualStudio.Modeling;

namespace Project.Co_DataTransformationPrototype
{
    public partial class DiagramForm : UserControl
    {
        private uint elementCount;
        private EventLogger logger;
        private ModelBuilder mBuilder;
        private ModelPublisher mPublisher;
        private MappingUtilities mappingUtilities;
        private UI.ScriptViewerForm dlgBoxScriptViewer;
        private UI.EventManagerForm dlgBoxEventManager;
        private Co_DataTransformationPrototypeDocView docView;

        private string validationErrorMsg = "Please address the validation errors. A model must be valid to ensure correct script generation.";

        public DiagramForm()
        {
            InitializeComponent();
            logger = EventLogger.GetInstance();
            logger.CollectionChanged += updateTreeview;
            mappingUtilities = MappingUtilities.GetInstance();
        }

        #region Access model from DiagramForm

        // Enable the form to access the model                
        internal DiagramForm(Co_DataTransformationPrototypeDocView docView, Control content)
            : this()
        {
            // Insert the DSL diagram into the Panel we've provided for it:
            pnlDiagram.Controls.Add(content);

            // Allows access to DSL from the form:
            this.docView = docView;
        }

        #endregion

        // TODO: Can the implementation be looser?
        private void updateTreeview(object sender, ModelEventArgs e)
        {
            if (trvEventHistory.IsDisposed)
            {
                trvEventHistory = new TreeView();
                this.Controls.Add(trvEventHistory);
            }
            trvEventHistory.AddDataSource(e.collection);
        }

        #region Validation - Button click
        private void btnValidate_Click(object sender, EventArgs e)
        {
            // Call the validation controller that is attached to the document, 
            // so that any errors appear in the errors window.
            // See http://msdn.microsoft.com/library/bb126413.aspx
            Co_DataTransformationPrototypeDocData docData = docView.DocData as Co_DataTransformationPrototypeDocData;
            docData.ValidationController.Validate(docData.Store, Microsoft.VisualStudio.Modeling.Validation.ValidationCategories.Menu);
        }
        #endregion

        #region Import Functionality - Button click
        /// <summary>
        /// Import a model
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnImport_Click(object sender, EventArgs e)
        {
            if (!bkgrwImport.IsBusy)
            {
                btnImport.Enabled = false;
                btnValidate.Enabled = false;
                btnViewEventManager.Enabled = false;
                btnViewScript.Enabled = false;
                btnPublishChanges.Enabled = false;
                chkbDisableRecorder.Enabled = false;
                lblProgressText.Text = "Connecting to CRM Server...";
                lblProgressText.Visible = true;
                prgbAsynCall.Visible = true;

                mBuilder = CRMModelBuilder.GetInstance(this.docView.CurrentDiagram.ModelElement as ModelRoot);
                lblProgressText.Text = "Creating Model based on CRM MetaData...";
                ModelBuilder.isImporting = true;
                logger.blnDisableChangeTracking = true;

                mBuilder.BuildDiagram(Microsoft.VisualBasic.Interaction.InputBox("Enter main entity name", "Select main entity", "account"));
                
                ModelBuilder.isImporting = false;
                logger.blnDisableChangeTracking = false;
                prgbAsynCall.Visible = false;
                lblProgressText.Visible = false;
                btnImport.Enabled = true;
                btnValidate.Enabled = true;
                btnViewEventManager.Enabled = true;
                btnViewScript.Enabled = true;
                btnPublishChanges.Enabled = true;
                chkbDisableRecorder.Enabled = true;

                //System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

                //bkgrwImport.WorkerReportsProgress = false;
                //bkgrwImport.WorkerSupportsCancellation = false;
                //// Start async connection call
                //this.bkgrwImport.RunWorkerAsync();
            }
        }

        private void bkgrwImport_DoWork(object sender, DoWorkEventArgs e)
        {
            //mBuilder.BuildDiagram("account");
        }

        private void bkgrwImport_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //ModelBuilder.isImporting = false;
            //logger.blnDisableChangeTracking = false;
            //prgbAsynCall.Visible = false;
            //lblProgressText.Visible = false;
            //btnImport.Enabled = true;
            //btnValidate.Enabled = true;
            //btnViewScript.Enabled = true;
            //btnPublishChanges.Enabled = true;
        }
        #endregion

        #region Display Event Manager Window

        private void btnViewEventManager_Click(object sender, EventArgs e)
        {
            //if (!bkgrwGenerate.IsBusy)
            //{
                btnViewEventManager.Enabled = false;                
                btnImport.Enabled = false;
                btnValidate.Enabled = false;
                btnViewScript.Enabled = false;
                btnPublishChanges.Enabled = false;

                showEMDialog();
                
                //lblProgressText.Text = "Collecting events...";
                //lblProgressText.Visible = true;
                //prgbAsynCall.Visible = true;

                //System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

                //bkgrwGenerate.WorkerReportsProgress = false;
                //bkgrwGenerate.WorkerSupportsCancellation = false;
                //// Start async generate call
                //this.bkgrwGenerate.RunWorkerAsync();
            //}
        }
       
        private void showEMDialog()
        {
            lblProgressText.Text = "Completed collection task.";
            prgbAsynCall.Visible = false;
            lblProgressText.Visible = false;
            btnViewEventManager.Enabled = true;
            btnImport.Enabled = true;
            btnValidate.Enabled = true;
            btnViewScript.Enabled = true;
            btnPublishChanges.Enabled = true;

            dlgBoxEventManager = new UI.EventManagerForm(logger.EventCollection);
            dlgBoxEventManager.ShowDialog(this);
        }
        #endregion

        #region View Transformation Script
        private void btnViewScript_Click(object sender, EventArgs e)
        {
            // Model must be valid
            btnValidate_Click(sender, e);

            if ((docView.DocData as Co_DataTransformationPrototypeDocData).ValidationController.ValidationMessages.Count < 1)
            {
                // Skip if there are no entities
                if (logger.EventCollection.Count > 0)
                {
                    if (!bkgrwGenerate.IsBusy)
                    {
                        btnViewScript.Enabled = false;
                        btnImport.Enabled = false;
                        btnValidate.Enabled = false;
                        btnViewEventManager.Enabled = false;
                        btnPublishChanges.Enabled = false;
                        chkbDisableRecorder.Enabled = false;
                        lblProgressText.Text = "Generating transformation script...";
                        lblProgressText.Visible = true;
                        prgbAsynCall.Visible = true;
                        
                        System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

                        bkgrwGenerate.WorkerReportsProgress = false;
                        bkgrwGenerate.WorkerSupportsCancellation = false;
                        // Start async generate call
                        this.bkgrwGenerate.RunWorkerAsync();
                    }
                }
                else
                {
                    MessageBox.Show("Cannot generate script for an empty adaptation-event history.", "Script Generation", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show(validationErrorMsg, "Script Generation", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void bkgrwGenerate_DoWork(object sender, DoWorkEventArgs e)
        {
            dlgBoxScriptViewer = new UI.ScriptViewerForm(mappingUtilities.initializeMappingGeneration(logger.EventCollection));
        }

        private void bkgrwGenerate_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblProgressText.Text = "Completed generation task.";
            prgbAsynCall.Visible = false;
            lblProgressText.Visible = false;
            btnViewScript.Enabled = true;
            btnViewEventManager.Enabled = true;
            btnImport.Enabled = true;
            btnValidate.Enabled = true;
            btnPublishChanges.Enabled = true;
            chkbDisableRecorder.Enabled = true;

            dlgBoxScriptViewer.ShowDialog(this);
        }
        #endregion

        #region Publish Functionality - Button click
        private void btnPublishChanges_Click(object sender, EventArgs e)
        {
            this.docView.CountObjects(1, out elementCount);

            // Skip if there are no entities
            if (elementCount > 1)
            {
                // Model must be valid
                btnValidate_Click(sender, e);
                if ((docView.DocData as Co_DataTransformationPrototypeDocData).ValidationController.ValidationMessages.Count < 1)
                {
                    Data.DbaseDialogBox dlgBox = new Data.DbaseDialogBox();
                    DialogResult dlgrResult = dlgBox.ShowDialog(this);
                    if (dlgrResult == DialogResult.OK)
                    {
                        if (!bkgrwPublish.IsBusy)
                        {
                            btnPublishChanges.Enabled = false;
                            btnImport.Enabled = false;
                            btnValidate.Enabled = false;
                            btnViewEventManager.Enabled = false;
                            btnViewScript.Enabled = false;
                            chkbDisableRecorder.Enabled = false;
                            lblProgressText.Text = "Creating staging database...";
                            lblProgressText.Visible = true;
                            prgbAsynCall.Visible = true;

                            bkgrwPublish.WorkerReportsProgress = false;
                            bkgrwPublish.WorkerSupportsCancellation = false;
                            // Start async publish call
                            this.bkgrwPublish.RunWorkerAsync();
                        }
                    }
                    dlgBox.Dispose();
                }
                else
                {
                    MessageBox.Show(validationErrorMsg, "Publishing Model", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show("Cannot publish empty model.", "Publishing Model", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void bkgrwPublish_DoWork(object sender, DoWorkEventArgs e)
        {
            if (mPublisher == null)
                mPublisher = new CRMModelPublisher(this.docView.CurrentDiagram.ModelElement as ModelRoot);
            
            mPublisher.publishModel();
        }

        private void bkgrwPublish_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblProgressText.Text = "Completed publishing task.";
            prgbAsynCall.Visible = false;
            lblProgressText.Visible = false;
            btnPublishChanges.Enabled = true;
            btnImport.Enabled = true;
            btnValidate.Enabled = true;
            btnViewScript.Enabled = true;
            btnViewEventManager.Enabled = true;
            chkbDisableRecorder.Enabled = true;
        }
        #endregion

        #region Disable Change Recording
        private void chkbDisableRecorder_CheckedChanged(object sender, EventArgs e)
        {
            logger.blnDisableChangeTracking = chkbDisableRecorder.Checked;
        }
        #endregion
               
    }

}
